module decoder_2to4(A, Y);
	//端口定义
	input [1: 0] A;
	output [3 : 0] Y;
	wire nA0, nA1; //内部连线
	
	//门级描述
	not n2(nA0, A[0]), n3(nA1, A[1]);
	and nd1(Y[0], nA0, nA1), nd2(Y[1], A[0], nA1),
		 nd3(Y[2], nA0, A[1]), nd4(Y[3], A[1], A[0]);
endmodule

module decoder_3to8(
	input logic [2: 0] in,
	output logic [7: 0] out
);
	always_comb begin
		case(in)
		3'b000: out=8'h01;
		3'b001: out=8'h02;
		3'b010: out=8'h04;
		3'b011: out=8'h08;
		3'b100: out=8'h10;
		3'b101: out=8'h20;
		3'b110: out=8'h40;
		3'b111: out=8'h80;
		endcase
	end
endmodule

module decoder_4to16(
	input logic [3: 0] in,
	output logic [15: 0] out
);
	always_comb begin
		case(in)
		4'h0: out=16'h0001;
		4'h1: out=16'h0002;
		4'h2: out=16'h0004;
		4'h3: out=16'h0008;
		4'h4: out=16'h0010;
		4'h5: out=16'h0020;
		4'h6: out=16'h0040;
		4'h7: out=16'h0080;
		4'h8: out=16'h0100;
		4'h9: out=16'h0200;
		4'ha: out=16'h0400;
		4'hb: out=16'h0800;
		4'hc: out=16'h1000;
		4'hd: out=16'h2000;
		4'he: out=16'h4000;
		4'hf: out=16'h8000;
		endcase
	end
endmodule

module decoder_6to64(
	input logic [5: 0] in,
	input logic en,
	output logic [63: 0] out
);
	logic [3: 0] de1;
	logic [15: 0] out1;
	decoder_2to4 d1(in[5: 4], de1);
	decoder_4to16 d2(in[3: 0], out1);
	assign out = {{16{en & de1[3]}} & out1, {16{en & de1[2]}} & out1, {16{en & de1[1]}} & out1, {16{en & de1[0]}} & out1};
endmodule

module decoder_multi #(
	parameter RADIX=16,
	parameter WIDTH=$clog2(RADIX)
)(
	input logic [WIDTH-1: 0] in,
	output logic [RADIX-1: 0] out
);
	generate;
		case(WIDTH)
		2: decoder_2to4 encoder(in, out);
		3: decoder_3to8 encoder(in, out);
		4: decoder_4to16 encoder(in, out);
		6: decoder_6to64 encoder(in, out);
		default: decoder_2to4 encoder(in, out);
		endcase
	endgenerate
endmodule

module encoder_4to2(
	input logic [3: 0] in,
	output logic [1: 0] out
);
	assign out[0] = in[1] | in[3];
	assign out[1] = in[2] | in[3];
endmodule

module encoder_6to3(
	input logic [5: 0] in,
	output logic [2: 0] out
);
	assign out[0] = in[1] | in[3] | in[5];
	assign out[1] = in[2] | in[3];
	assign out[2] = in[4] | in[5];
endmodule

module encoder_8to3(
	input logic [7: 0] in,
	output logic [2: 0] out
);
	assign out[2] = in[4] | in[5] | in[6] | in[7];
	assign out[1] = in[2] | in[3] | in[6] | in[7];
	assign out[0] = in[1] | in[3] | in[5] | in[7];
endmodule

module encoder_16to4(
	input logic [15: 0] in,
	output logic [3: 0] out
);
	logic [2: 0] out_high, out_low;
	encoder_8to3 high(in[7: 0], out_low);
	encoder_8to3 low(in[15: 8], out_high);
	assign out[3] = |in[15: 8];
	assign out[2: 0] = out[3] ? out_high : out_low;
endmodule

module encoder_64to6(
	input logic [63: 0] in,
	output logic [5: 0] out
);
	logic [3: 0] out1, out2, out3, out4;
	encoder_16to4 part1(in[15: 0], out1);
	encoder_16to4 part2(in[31: 16], out2);
	encoder_16to4 part3(in[47: 32], out3);
	encoder_16to4 part4(in[63: 48], out4);
	logic [3: 0] select;
	assign select[0] = |in[15: 0];
	assign select[1] = |in[31: 16];
	assign select[2] = |in[47: 32];
	assign select[3] = |in[63: 48];
	encoder_4to2 encoder(select, out[5: 4]);
	assign out[3: 0] = {4{select[0]}} & out1 | {4{select[1]}} & out2 | {4{select[2]}} & out3 | {4{select[3]}} & out4;
endmodule

module encoder_multi #(
	parameter RADIX=16,
	parameter WIDTH=$clog2(RADIX)
)(
	input logic [RADIX-1: 0] in,
	output logic [WIDTH-1: 0] out
);
	generate;
		case(RADIX)
		4: encoder_4to2 encoder(in, out);
		8: encoder_8to3 encoder(in, out);
		16: encoder_16to4 encoder(in, out);
		64: encoder_64to6 encoder(in, out);
		default: encoder_4to2 encoder(in, out);
		endcase
	endgenerate
endmodule

module priority_selector4(
	input logic [3: 0] in,
	output logic [3: 0] out
);
	always_comb begin
		if(in[3])begin
			out = 4'b1000;
		end
		else if(in[2])begin
			out = 4'b0100;
		end
		else if(in[1])begin
			out = 4'b0010;
		end
		else begin
			out = 4'b0001;
		end
	end
endmodule

module priority_selector6(
	input logic [5 :0] in,
	output logic [5: 0] out
);
	assign out[0] = in[0];
	assign out[1] = ~in[0] & in[1];
	assign out[2] = ~in[0] & ~in[1] & in[2];
	assign out[3] = ~in[0] & ~in[1] & ~in[2] & in[3];
	assign out[4] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & in[4];
	assign out[5] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & in[5];
endmodule

module priority_selector8(
	input logic [7: 0] in,
	output logic [7: 0] out
);
	assign out[0] = in[0];
	assign out[1] = ~in[0] & in[1];
	assign out[2] = ~in[0] & ~in[1] & in[2];
	assign out[3] = ~in[0] & ~in[1] & ~in[2] & in[3];
	assign out[4] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & in[4];
	assign out[5] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & in[5];
	assign out[6] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & ~in[5] & in[6];
	assign out[7] = ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & ~in[5] & ~in[6] & in[7];	
endmodule

module priority_selector9_reverse(
	input logic [8: 0] in,
	output logic [8: 0] out
);
	assign out[8] = in[8];
	assign out[7] = ~in[8] & in[7];
	assign out[6] = ~in[8] & ~in[7] & in[6];
	assign out[5] = ~in[8] & ~in[7] & ~in[6] & in[5];
	assign out[4] = ~in[8] & ~in[7] & ~in[6] & ~in[5] & in[4];
	assign out[3] = ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & in[3];
	assign out[2] = ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & in[2];
	assign out[1] = ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & in[1];
	assign out[0] = ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & ~in[1] & in[0];
endmodule

module priority_selector10_reverse(
	input logic [9: 0] in,
	output logic [9: 0] out
);
	assign out[9] = in[9];
	assign out[8] = ~in[9] & in[8];
	assign out[7] = ~in[9] & ~in[8] & in[7];
	assign out[6] = ~in[9] & ~in[8] & ~in[7] & in[6];
	assign out[5] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & in[5];
	assign out[4] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & in[4];
	assign out[3] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & in[3];
	assign out[2] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & in[2];
	assign out[1] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & in[1];
	assign out[0] = ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & ~in[1] & in[0];
endmodule

module priority_selector11_reverse(
	input logic [10: 0] in,
	output logic [10: 0] out
);
	assign out[10] = in[10];
	assign out[9] = ~in[10] & in[9];
	assign out[8] = ~in[10] & ~in[9] & in[8];
	assign out[7] = ~in[10] & ~in[9] & ~in[8] & in[7];
	assign out[6] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & in[6];
	assign out[5] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & in[5];
	assign out[4] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & in[4];
	assign out[3] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & in[3];
	assign out[2] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & in[2];
	assign out[1] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & in[1];
	assign out[0] = ~in[10] & ~in[9] & ~in[8] & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & ~in[1] & in[0];
endmodule

module priority_selector8_ahead(
	input logic ahead,
	input logic [7: 0] in,
	output logic [7: 0] out
);
	assign out[0] = ahead & in[0];
	assign out[1] = ahead & ~in[0] & in[1];
	assign out[2] = ahead & ~in[0] & ~in[1] & in[2];
	assign out[3] = ahead & ~in[0] & ~in[1] & ~in[2] & in[3];
	assign out[4] = ahead & ~in[0] & ~in[1] & ~in[2] & ~in[3] & in[4];
	assign out[5] = ahead & ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & in[5];
	assign out[6] = ahead & ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & ~in[5] & in[6];
	assign out[7] = ahead & ~in[0] & ~in[1] & ~in[2] & ~in[3] & ~in[4] & ~in[5] & ~in[6] & in[7];
endmodule

module priority_selector8_ahead_reverse(
	input logic ahead,
	input logic [7: 0] in,
	output logic [7: 0] out
);
	assign out[7] = ahead & in[7];
	assign out[6] = ahead & ~in[7] & in[6];
	assign out[5] = ahead & ~in[7] & ~in[6] & in[5];
	assign out[4] = ahead & ~in[7] & ~in[6] & ~in[5] & in[4];
	assign out[3] = ahead & ~in[7] & ~in[6] & ~in[5] & ~in[4] & in[3];
	assign out[2] = ahead & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & in[2];
	assign out[1] = ahead & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & in[1];
	assign out[0] = ahead & ~in[7] & ~in[6] & ~in[5] & ~in[4] & ~in[3] & ~in[2] & ~in[1] & in[0];
endmodule

module priority_selector64(
	input logic [63: 0] in,
	output logic [63: 0] out
);
	logic [7: 0] _or, ahead;
	assign _or[0] = |in[7: 0];
	assign _or[1] = |in[15: 8];
	assign _or[2] = |in[23: 16];
	assign _or[3] = |in[31: 24];
	assign _or[4] = |in[39: 32];
	assign _or[5] = |in[47: 40];
	assign _or[6] = |in[55: 48];
	assign _or[7] = |in[63: 56];
	assign ahead[0] = _or[0];
	assign ahead[1] = ~_or[0] & _or[1];
	assign ahead[2] = ~_or[0] & ~_or[1] & _or[2];
	assign ahead[3] = ~_or[0] & ~_or[1] & ~_or[2] & _or[3];
	assign ahead[4] = ~_or[0] & ~_or[1] & ~_or[2] & ~_or[3] & _or[4];
	assign ahead[5] = ~_or[0] & ~_or[1] & ~_or[2] & ~_or[3] & ~_or[4] & _or[5];
	assign ahead[6] = ~_or[0] & ~_or[1] & ~_or[2] & ~_or[3] & ~_or[4] & ~_or[5] & _or[6];
	assign ahead[7] = ~_or[0] & ~_or[1] & ~_or[2] & ~_or[3] & ~_or[4] & ~_or[5] & ~_or[6] & _or[7];
	priority_selector8_ahead selector0(ahead[0], in[7: 0], out[7: 0]);
	priority_selector8_ahead selector1(ahead[1], in[15: 8], out[15: 8]);
	priority_selector8_ahead selector2(ahead[2], in[23: 16], out[23: 16]);
	priority_selector8_ahead selector3(ahead[3], in[31: 24], out[31: 24]);
	priority_selector8_ahead selector4(ahead[4], in[39: 32], out[39: 32]);
	priority_selector8_ahead selector5(ahead[5], in[47: 40], out[47: 40]);
	priority_selector8_ahead selector6(ahead[6], in[55: 48], out[55: 48]);
	priority_selector8_ahead selector7(ahead[7], in[63: 56], out[63: 56]);
endmodule

module priority_selector64_reverse(
	input logic [63: 0] in,
	output logic [63: 0] out
);
	logic [7: 0] _or, ahead;
	assign _or[0] = |in[7: 0];
	assign _or[1] = |in[15: 8];
	assign _or[2] = |in[23: 16];
	assign _or[3] = |in[31: 24];
	assign _or[4] = |in[39: 32];
	assign _or[5] = |in[47: 40];
	assign _or[6] = |in[55: 48];
	assign _or[7] = |in[63: 56];
	assign ahead[7] = _or[7];
	assign ahead[6] = ~_or[7] & _or[6];
	assign ahead[5] = ~_or[7] & ~_or[6] & _or[5];
	assign ahead[4] = ~_or[7] & ~_or[6] & ~_or[5] & _or[4];
	assign ahead[3] = ~_or[7] & ~_or[6] & ~_or[5] & ~_or[4] & _or[3];
	assign ahead[2] = ~_or[7] & ~_or[6] & ~_or[5] & ~_or[4] & ~_or[3] & _or[2];
	assign ahead[1] = ~_or[7] & ~_or[6] & ~_or[5] & ~_or[4] & ~_or[3] & ~_or[2] & _or[1];
	assign ahead[0] = ~_or[7] & ~_or[6] & ~_or[5] & ~_or[4] & ~_or[3] & ~_or[2] & ~_or[1] & _or[0];
	priority_selector8_ahead_reverse selector0(ahead[0], in[7: 0], out[7: 0]);
	priority_selector8_ahead_reverse selector1(ahead[1], in[15: 8], out[15: 8]);
	priority_selector8_ahead_reverse selector2(ahead[2], in[23: 16], out[23: 16]);
	priority_selector8_ahead_reverse selector3(ahead[3], in[31: 24], out[31: 24]);
	priority_selector8_ahead_reverse selector4(ahead[4], in[39: 32], out[39: 32]);
	priority_selector8_ahead_reverse selector5(ahead[5], in[47: 40], out[47: 40]);
	priority_selector8_ahead_reverse selector6(ahead[6], in[55: 48], out[55: 48]);
	priority_selector8_ahead_reverse selector7(ahead[7], in[63: 56], out[63: 56]);
endmodule

module priority_selector_reverse_multi #(
	parameter RADIX=4
)(
	input logic [RADIX-1: 0] in,
	output logic [RADIX-1: 0] out
);
	logic [RADIX-1: 0] reverse;
	assign reverse[RADIX-1] = 1'b1;
	for(genvar i=RADIX-2; i>=0; i--)begin
		assign reverse[i] = ~in[i+1] & reverse[i+1];
	end
	for(genvar i=0; i<RADIX; i++)begin
		assign out[i] = reverse[i] & in[i];
	end
endmodule

module priority_encoder_4to2(
	input logic [3: 0] in,
	output logic [1: 0] out
);
	always_comb begin
		if(in[3]) out = 2'b11;
		else if(in[2]) out = 2'b10;
		else if(in[1]) out = 2'b01;
		else if(in[0]) out = 2'b00;
		else out = 2'b00;
	end
endmodule

module priority_encoder_8to3(
	input logic [7: 0] in,
	output logic [2: 0] out
);
	always_comb begin
		if(in[7]) out = 3'b111;
		else if(in[6]) out = 3'b110;
		else if(in[5]) out = 3'b101;
		else if(in[4]) out = 3'b100;
		else if(in[3]) out = 3'b011;
		else if(in[2]) out = 3'b010;
		else if(in[1]) out = 3'b001;
		else out = 3'b000;
	end
	// assign out[2] = ~in[6] & (~in[4] & ~in[2] & in[1] | ~in[4] & in[3] | in[5]) | in[7];
	// assign out[1] = in[5] & in[4] & (in[2] | in[3]) | in[6] | in[7];
	// assign out[0] = in[4] | in[5] | in[6] | in[7];
endmodule

module priority_encoder_9to4(
	input logic [8: 0] in,
	output logic [3: 0] out
);
	always_comb begin
		if(in[8]) out = 4'b1000;
		else if(in[7]) out = 4'b111;
		else if(in[6]) out = 4'b110;
		else if(in[5]) out = 4'b101;
		else if(in[4]) out = 4'b100;
		else if(in[3]) out = 4'b011;
		else if(in[2]) out = 4'b010;
		else if(in[1]) out = 4'b001;
		else out = 4'b000;
	end
endmodule

module priority_encoder_10to4(
	input logic [9: 0] in,
	output logic [3: 0] out
);
	always_comb begin
		if(in[9]) out = 4'b1001;
		else if(in[8]) out = 4'b1000;
		else if(in[7]) out = 4'b111;
		else if(in[6]) out = 4'b110;
		else if(in[5]) out = 4'b101;
		else if(in[4]) out = 4'b100;
		else if(in[3]) out = 4'b011;
		else if(in[2]) out = 4'b010;
		else if(in[1]) out = 4'b001;
		else out = 4'b000;
	end
endmodule

module priority_encoder_11to4(
	input logic [10: 0] in,
	output logic [3: 0] out
);
	always_comb begin
		if (in[10]) out = 4'b1010;
		else if(in[9]) out = 4'b1001;
		else if(in[8]) out = 4'b1000;
		else if(in[7]) out = 4'b111;
		else if(in[6]) out = 4'b110;
		else if(in[5]) out = 4'b101;
		else if(in[4]) out = 4'b100;
		else if(in[3]) out = 4'b011;
		else if(in[2]) out = 4'b010;
		else if(in[1]) out = 4'b001;
		else out = 4'b000;
	end
endmodule

module priority_encoder_16to4(
	input logic [15: 0] in,
	output logic [3: 0] out
);
	logic [2: 0] out1, out2;
	logic is_high;
	priority_encoder_8to3 high(in[15: 8], out1);
	priority_encoder_8to3 low(in[7: 0], out2);
	assign is_high = |in[15: 8];
	assign out[3] = is_high;
	assign out[2: 0] = is_high ? out1 : out2;
endmodule

module priority_encoder_32to5(
	input logic [31: 0] in,
	output logic [4: 0] out
);
	logic [2: 0] out1, out2, out3, out4;
	logic [3: 0] _or;
	priority_encoder_8to3 encoder2(in[15: 8], out2);
	priority_encoder_8to3 encoder1(in[7: 0], out1);
	priority_encoder_8to3 encoder3(in[23: 16], out3);
	priority_encoder_8to3 encoder4(in[31: 24], out4);
	assign _or[0] = |in[7: 0];
	assign _or[1] = |in[15: 8];
	assign _or[2] = |in[23: 16];
	assign _or[3] = |in[31: 24];
	priority_encoder_4to2 encoder_high(_or, out[4: 3]);
	assign out[2: 0] = out[4: 3] == 2'b11 ? out4 : out[4: 3] == 2'b10 ? out3 : out[4: 3] == 2'b01 ? out2 : out1;
	// assign out[4: 3] = _or[3] ? 2'b11 : _or[2] ? 2'b10 : _or[1] ? 2'b01 : 2'b00;
	// assign out[2: 0] = _or[3] ? out4 : _or[2] ? out3 : _or[1] ? out2 : out1;
endmodule

module priority_encoder_64to6(
	input logic [63: 0] in,
	output logic [5: 0] out
);
	logic [7: 0] _or;
	logic [7: 0][2: 0] low;
	assign _or[0] = |in[7: 0];
	assign _or[1] = |in[15: 8];
	assign _or[2] = |in[23: 16];
	assign _or[3] = |in[31: 24];
	assign _or[4] = |in[39: 32];
	assign _or[5] = |in[47: 40];
	assign _or[6] = |in[55: 48];
	assign _or[7] = |in[63: 56];
	priority_encoder_8to3 encoder_high(_or, out[5: 3]);
	priority_encoder_8to3 encoder_low1(in[7: 0], low[0]);
	priority_encoder_8to3 encoder_low2(in[15: 8], low[1]);
	priority_encoder_8to3 encoder_low3(in[23: 16], low[2]);
	priority_encoder_8to3 encoder_low4(in[31: 24], low[3]);
	priority_encoder_8to3 encoder_low5(in[39: 32], low[4]);
	priority_encoder_8to3 encoder_low6(in[47: 40], low[5]);
	priority_encoder_8to3 encoder_low7(in[55: 48], low[6]);
	priority_encoder_8to3 encoder_low8(in[63: 56], low[7]);
	assign out[2: 0] = low[out[5: 3]];
endmodule

module priority_encoder_multi#(
	parameter RADIX=16,
	parameter WIDTH=$clog2(RADIX)
)(
	input logic [RADIX-1: 0] in,
	output logic [WIDTH-1: 0] out
);
	generate;
		case(RADIX)
		'd4: priority_encoder_4to2 priority_encoder(in, out);
		'd8: priority_encoder_8to3 priority_encoder(in, out);
		'd9: priority_encoder_9to4 priority_encoder(in, out);
		'd10: priority_encoder_10to4 priority_encoder(in, out);
		'd11: priority_encoder_11to4 priority_encoder(in, out);
		'd16: priority_encoder_16to4 priority_encoder(in, out);
		'd32: priority_encoder_32to5 priority_encoder(in, out);
		'd64: priority_encoder_64to6 priority_encoder(in, out);
		default: priority_encoder_4to2 priority_encoder(in, out);
		endcase
	endgenerate
endmodule

module bit_expander_4to32(
	input logic [3: 0] in,
	output logic [31: 0] out
);
	assign out = {{8{in[3]}}, {8{in[2]}}, {8{in[1]}}, {8{in[0]}}};
	// for(genvar i=0; i<8; i++)begin
	// 	assign out[i] = in[0];
	// 	assign out[i+8] = in[1];
	// 	assign out[i+16] = in[2];
	// 	assign out[i+24] = in[3];
	// end
endmodule

// buffer_index, direction, valid, rob_index 
// buffer_index: 10-8 direction: 7 valid: 6 rob_index: 5: 0
module compareUtil
#(parameter BUFFER_SIZE=36,
parameter DIRECTION_INDEX=32,
parameter BUFFER_INDEX_WIDTH=3,
parameter ROB_INDEX_WIDTH=6,
parameter ROB_INDEX=13)(
	input logic [1: 0] 	ready,
	input logic [BUFFER_INDEX_WIDTH-1: 0] 	index,
	input logic [BUFFER_INDEX_WIDTH-1: 0] 	next_index,
	input logic 		direction1,
	input logic 		direction2,
	input logic [ROB_INDEX_WIDTH-1: 0]	rob_index1,
	input logic [ROB_INDEX_WIDTH-1: 0]	rob_index2,
	output logic [BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: 0] compare
);

	always_comb begin
		case(ready)
			2'b00:begin
				compare = (1 << ROB_INDEX_WIDTH) - 1;
			end
			2'b01:begin
				compare = {index, direction1, 1'b1, rob_index1};
			end
			2'b10:begin
				compare = {next_index, direction2, 1'b1, rob_index2};
			end
			2'b11:begin
				if(direction1 == direction2)begin
					if(rob_index1 < rob_index2)begin
						compare = {index, direction1, 1'b1, rob_index1};
					end
					else begin
						compare = {next_index, direction2, 1'b1, rob_index2};
					end

				end
				else begin
					if(rob_index1 < rob_index2)begin
						compare = {next_index, direction2, 1'b1, rob_index2};
					end
					else begin
						compare = {index, direction1, 1'b1, rob_index1};
					end
				end
			end
		endcase		
	end

endmodule

module compareUtil2
#(parameter BUFFER_SIZE=36,
parameter DIRECTION_INDEX=32,
parameter BUFFER_INDEX_WIDTH=3,
parameter ROB_INDEX_WIDTH=6,
parameter ROB_INDEX=13)(
	input logic [BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: 0] input_compare1,
	input logic [BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: 0] input_compare2,
	output logic [BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: 0] compare
);
	always_comb begin
		case({input_compare2[ROB_INDEX_WIDTH], input_compare1[ROB_INDEX_WIDTH]})
		2'b00:begin
			compare = (1 << ROB_INDEX_WIDTH) - 1;
		end
		2'b01:begin
			compare = {input_compare1[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare1[ROB_INDEX_WIDTH+1], 1'b1, input_compare1[ROB_INDEX_WIDTH-1: 0]};
		end
		2'b10:begin
			compare = {input_compare2[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare2[ROB_INDEX_WIDTH+1], 1'b1, input_compare2[ROB_INDEX_WIDTH-1: 0]};
		end
		2'b11:begin
			if(input_compare1[ROB_INDEX_WIDTH+1] == input_compare2[ROB_INDEX_WIDTH+1])begin
				if(input_compare1[ROB_INDEX_WIDTH-1: 0] < input_compare2[ROB_INDEX_WIDTH-1: 0])begin
					compare = {input_compare1[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare1[ROB_INDEX_WIDTH+1], 1'b1, input_compare1[ROB_INDEX_WIDTH-1: 0]};
				end
				else begin
					compare = {input_compare2[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare2[ROB_INDEX_WIDTH+1], 1'b1, input_compare2[ROB_INDEX_WIDTH-1: 0]};
				end
			end
			else begin
				if(input_compare1[ROB_INDEX_WIDTH-1: 0] < input_compare2[ROB_INDEX_WIDTH-1: 0])begin
					compare = {input_compare2[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare2[ROB_INDEX_WIDTH+1], 1'b1, input_compare2[ROB_INDEX_WIDTH-1: 0]};
				end
				else begin
					compare = {input_compare1[BUFFER_INDEX_WIDTH+ROB_INDEX_WIDTH+1: ROB_INDEX_WIDTH+2], input_compare1[ROB_INDEX_WIDTH+1], 1'b1, input_compare1[ROB_INDEX_WIDTH-1: 0]};
				end
			end
		end
		endcase
	end
endmodule

module mux4 #(
	parameter WIDTH=32
) (
	input logic [WIDTH-1: 0] in1,
	input logic [WIDTH-1: 0] in2,
	input logic [WIDTH-1: 0] in3,
	input logic [WIDTH-1: 0] in4,
	input logic [1: 0] selector,
	output logic [WIDTH-1: 0] out	
);
	always_comb begin
		case(selector)
		2'b00: out = in1;
		2'b01: out = in2;
		2'b10: out = in3;
		2'b11: out = in4;
		endcase
	end
endmodule

module mux3 #(
	parameter WIDTH=32
)(
	input logic [WIDTH-1: 0] in1,
	input logic [WIDTH-1: 0] in2,
	input logic [WIDTH-1: 0] in3,
	input logic [1: 0] selector,
	output logic [WIDTH-1: 0] out
);
	always_comb begin
		case(selector)
		2'b00: out = in1;
		2'b01: out = in2;
		2'b10: out = in3;
		2'b11: out = 0;
		endcase
	end
endmodule

module UpCounter(
	input logic [1: 0] in,
	output logic [1: 0] out
);
	// assign out[1] = ~in[0] & (~in[1]);
	// assign out[0] = ~in[1] & in[0];
	always_comb begin
		case(in)
		2'b00: out=2'b01;
		2'b01: out=2'b10;
		2'b10: out=2'b11;
		2'b11: out=2'b11;
		endcase
	end
endmodule

module DownCounter(
	input logic [1: 0] in,
	output logic [1: 0] out
);
	// assign out[1] = in[1] & in[0];
	// assign out[0] = in[1] & (~in[0]);
	always_comb begin
		case(in)
		2'b00: out=2'b00;
		2'b01: out=2'b00;
		2'b10: out=2'b01;
		2'b11: out=2'b10;
		endcase
	end
endmodule